// 引入报错模块
const createError = require('http-errors');
// 引入express模块
const express = require('express');
// 引入path模块
const path = require('path');
// 引入处理cookie模块
const cookieParser = require('cookie-parser');
// 引入控制台打印模块
const logger = require('morgan');
// 引入express-session  登录用户信息验证
const session = require('express-session');
// 引入express-mysql-session模块让session持久化，因为session是保存在服务端内存中，nodejs重新启动后，session会丢失，所以可以让session保存到mysql数据库中做持久化
const mysql = require("mysql");
const MySQLStore = require('express-mysql-session')(session); //连接mysql主要模块

// mysql / http-errors / cookie-parser 第三方中间件

// 配置 mysql
const options = {
  host: 'localhost',
  port: 3306,
  user: 'root',
  password: '123456',    
  database: 'session'
};

// 创建session
const sessionStore = new MySQLStore(options);

// const sessionConnection = mysql.createConnection(options);

// const sessionStore = new MySQLStore({
//     expiration: 10800000,
//     createDatabaseTable: true,  //是否创建表
//     schema: {
//         tableName: 'session_tab',   //表名
//         columnNames: {      //列选项
//             session_id: 'session_id',
//             expires: 'expires',
//             data: 'data'
//         }
//     }
// }, sessionConnection);

// 引入路由文件
const indexRouter = require('./routes/index');

// 创建应用入口
const app = express();

// view engine setup 模板引擎
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'jade');

// 更换模板引擎
app.engine('html', require('express-art-template'));
// app.set('views', {
//   debug: process.env.NODE_ENV !== 'production'
// });
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');

// app.use(fn)   fn都是应用级中间件
// 打印中间件
app.use(logger('dev'));
// 处理post请求中间件
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 处理cookie中间件
app.use(cookieParser());
// 定义公共资源文件夹
app.use(express.static(path.join(__dirname, 'public')));

// express.json() / express.urlencoded() /express.static() 内置中间件

var a = 10;
var b = 20;
console.log(a+b);

// 使用全局的中间件
// app.use((req,res,next)=>{
//   console.log("我是全家中间件，也可以理解成全局守卫");
//   next();
// })

var c = 1;
var d = 2;
console.log(c+d);


/**
 * session
 *  secret：  一个 String 类型的字符串，作为服务器端生成 session 的签名
 *  name:    保存在本地cookie的一个名字 默认connect.sid  可以不设置
 *  resave:  强制保存 session 即使它并没有变化,。默认为 true。建议设置成 false。
 *  rolling: 在每次请求时强行设置 cookie，这将重置 cookie 过期时间（默认：false）
 *  saveUninitialized: 强制将未初始化的 session 存储。默认值是true,建议设置成true
 *
 * cookie
 *  属性默认值: { path: '/', httpOnly: true, secure: false, maxAge: null }
 *  httpOnly： 属性禁止客户端JavaScript的访问，禁止后不能使用document.cookie
 *  secure:    https这样的情况才可以访问cookie  http://localhost:9999/
 *  maxAge：   单位毫秒，从设置cookie开始多少毫秒失效(如果maxAge和expires都设置了，最后设置的属性生效.)
 *  path：     路径，默认值为域名的根路径 
 *  sameSite:  SameSite-cookies是一种机制，用于定义cookie如何跨域发送。
 */

// 配置session，需要在所有路由之前
app.use(session({
  secret: 'hellom',
  name: 'hellom.sid',
  resave: true,
  rolling: true,
  saveUninitialized: true,
  cookie: {
      secure: false,
      // domain: 'xxx.xxx.xxx.xxx:xxxx', // 域名
      path: '/',
      httpOnly: true,
      maxAge: 1000*60*60*24                 // 单位毫秒   1秒 = 1000毫秒 
  },
  store: sessionStore,  // 把session保存到mysql数据库中持久化
}));

// 1.客户端页面里使用js的window.onclose来监视浏览器的关闭动作，然后向服务器发送一个请求来关闭Session，但是这种做法在实际的开发中也是不推荐使用的，最正常的办法就是不去管它，让它等到默认的时间后，自动销毁。 2.手动销毁服务端的Session==>第1种情况是等到默认的时间后，自动销毁,推荐的做法；第2种情况是客户端页面里使用js点击按钮向服务器发送一个请求来关闭Session；第3种情况是客户端页面里使用js计算session的过期时间，通过倒计时的方式，等到时间后向服务器发送一个请求来关闭Session，这种方式完全没有必要；

// 使用路由
app.use('/', indexRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  res.render('404');
  // next(createError(404));
});

// error handler  错误处理中间件
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;